package com.xgxd.modules.servcie;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xgxd.commons.utils.*;
import com.xgxd.modules.entity.YmlGet;
import com.xgxd.modules.entity.YmlPut;
import com.xgxd.modules.po.SACTEIRYM;
import com.xgxd.modules.po.YmToAs400;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;

import java.beans.PropertyDescriptor;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;

@Service
public class EirService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private Environment environment;


    private final String SUCCESS = "S";

    private final String FAIL = "E";

    /**
     * 保存get接口信息
     *
     * @param y
     */
    public String saveYmlget(YmlGet y) {
//      String sql="insert into SACTEIRYM() values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        String sql = "INSERT INTO SACTEIRYM(YMEIRCNT, YMSEQN, YMSTAT, YMBKID, YMBLNO, YMSMBR, YMBKCUST, YMVSNM, YMVOY, YMVOYC, YMSALD, YMPOLC, YMPODC, YMDELC, YMCTID, YMCNTP, YMOPTR, YMCUST, YMYARTP, YMYARTPNM, YMYARTR, YMYARTRNM, YMBARCM, YMEIRRMK, YMEIRPUSR, YMEIRPDAT, YMRMK, YMDATTIM) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        jdbcTemplate.update(sql, beanToArrayInsert(y));
        return y.getUuid();
    }

    /**
     * 保存put接口信息
     *
     * @param y
     */
    public String saveYmlput(YmlPut y) {
        String sql = "insert into SACTEIRYM (YMEIRCNT, YMSEQN, YMSTAT, YMBKID, YMBLNO, YMSMBR, YMBKCUST, YMVSNM, YMVOY, YMVOYC, YMSALD, YMPOLC, YMPODC, YMDELC, YMCTID, YMCNTP, YMOPTR, YMCUST, YMYARTP, YMYARTPNM, YMYARTR, YMYARTRNM, YMBARCM, YMEIRRMK, YMEIRPUSR, YMEIRPDAT, YMRMK, YMDATTIM)  values(0,'" + y.getUuid() + "','" + y.getIsSuccess() + "','','','','','','','','" + y.getYmsald() + "','','','',0,'','','','','','','','','','','','" + y.getTryMessage() + "','" + DateUtils.getDateTime() + "')";
        jdbcTemplate.update(sql);
        return y.getUuid();
    }

    /**
     * 查询阳明接口信息
     *
     * @param ymseqn
     * @return
     */
    public List<Map<String, Object>> get(String ymseqn) {
        List<Map<String, Object>> map = null;
        try {
            String sql = "select * from SACTEIRYM WHERE YMSEQN=? and YMSTAT !='E' ";
            map = jdbcTemplate.queryForList(sql, ymseqn);
        } catch (EmptyResultDataAccessException e) {
            return map;
        }
        return map;
    }


    public Object[] beanToArrayInsert(YmlGet y) {
        YmToAs400 ymToAs400 = new YmToAs400();
        SACTEIRYM s = ymToAs400.YmlToBaen(y);
        Object[] objects = new Object[]{
                s.getYMEIRCNT() == null ? 0 : s.getYMEIRCNT(),
                s.getYMSEQN(),
                s.getYMSTAT() == null ? "" : s.getYMSTAT(),
                s.getYMBKID(),
                s.getYMBLNO(),
                s.getYMSMBR(),
                s.getYMBKCUST(),
                s.getYMVSNM(),
                s.getYMVOY(),
                s.getYMVOYC(),
                s.getYMSALD(),
                s.getYMPOLC(),
                s.getYMPODC(),
                s.getYMDELC(),
                s.getYMCTID() == null ? 0 : s.getYMCTID(),
                s.getYMCNTP(),
                s.getYMOPTR(),
                s.getYMCUST(),
                s.getYMYARTP(),
                s.getYMYARTPNM(),
                s.getYMYARTR(),
                s.getYMYARTRNM(),
                be(s.getYMBARCM()),
                s.getYMEIRRMK(),
                s.getYMEIRPUSR(),
                s.getYMEIRPDAT(),
                s.getYMRMK(),
                s.getYMDATTIM()
        };
        return objects;
    }

    public String be(String str) {
        if ("".equals(str)) {
            return "";
        } else {
            return "true".equals(str) ? "Y" : "N";
        }
    }

    public Map<String, Object> mapToBean(Map<String, Object> map) {
        Map<String, Object> m = new HashMap<>();
        if (StringUtils.isBlank(map.get("YMBKID").toString())){
            m.put("bkid", 0);
        }else {
            m.put("bkid", Integer.valueOf(map.get("YMBKID").toString().trim()));
        }

        m.put("bknbr", map.get("YMBLNO").toString());
        m.put("vslname", map.get("YMVSNM").toString());
        m.put("voyage", map.get("YMVOY").toString());
        m.put("cntrid", (map.get("YMCTID").toString() == null ? "" : map.get("YMCTID").toString()));
        m.put("cntrtype", (map.get("YMCNTP").toString()));
        m.put("cntrcarrier", (map.get("YMCUST").toString()));
        m.put("cntrepdname", (map.get("YMYARTPNM").toString()));
        m.put("cntrfrdname", (map.get("YMYARTRNM").toString()));
        m.put("printedby", (map.get("YMEIRPUSR").toString()));
        m.put("printedon", (map.get("YMEIRPDAT").toString()));
//         y.setBkid(map.get("YMBKID").toString());
//        y.setBknbr(map.get("YMBLNO").toString());
//        y.setVslname(map.get("YMVSNM").toString());
//        y.setVoyage(map.get("YMVOY").toString());
//        y.setCntrid(map.get("YMCTID").toString() == null ? "" : map.get("YMCTID").toString());
//        y.setCntrtype(map.get("YMCNTP").toString());
//        y.setCntrcarrier(map.get("YMCUST").toString());
//        y.setCntrepdname(map.get("YMYARTPNM").toString());
//        y.setCntrfrdname(map.get("YMYARTRNM").toString());
//        y.setPrintedby(map.get("YMEIRPUSR").toString());
//        y.setPrintedon(map.get("YMEIRPDAT").toString());
        return m;
    }

    /*
     *
     *  基础map
     * @param api 调用api地址
     * @return
     */
    public Map BaseMap(String api, String key) throws UnsupportedEncodingException {
        Map map = new TreeMap();
        map.put("app_key", key);
        map.put("format", "json");
        map.put("method", api);
        map.put("nonce", NumberUtil.getRandomStringByLength(3));
        map.put("timestamp", DateUtils.formatDateTime(new Date()));
        return map;
    }

    public String ymlPut(String id) {
        System.out.println("============进入put" + DateUtils.getDateTime());
        long startTime = System.currentTimeMillis();//记录开始时间
        String uuid = SqenUtils.uuid();
        YmlPut y = new YmlPut();
        try {
            String resetJson = "";

            //put业务参数
            Map<String, Object> dataMap= this.get(id).get(0);
                Map baseMap = BaseMap("yml.exp.ep.pr.put", environment.getProperty("app_key_formal"));
                Map<String, Object> m = mapToBean(dataMap);
                baseMap.putAll(m);
                //签名计算
                String sign = getSign(baseMap, environment.getProperty("app_secret_formal"));
                baseMap.put("sign", sign);
                System.out.println("============开始调用put" + DateUtils.getDateTime());
                resetJson = sendPost(environment.getProperty("api_http_formal"), createLinkStringByGet(baseMap));
                JSONObject j = (JSONObject) JSONObject.parse(resetJson);
                if (j.containsKey("error_response")) {
                    //记录调用方编号
                    y.setYmsald(id);
                    y.setIsSuccess(FAIL);
                  String msg=  j.getJSONObject("error_response").get("desc").toString().replace("\"", "");
                  if (msg.length()>20){
                      msg.substring(0,19);
                  }
                    y.setTryMessage("msg");
                    y.setUuid(uuid);
                } else {
                    //记录调用方编号
                    y.setYmsald(id);
                    y.setIsSuccess(SUCCESS);
                    y.setTryMessage("ok");
                    y.setUuid(uuid);
                }

            this.saveYmlput(y);
        } catch (Exception e) {
            //记录调用方编号
            y.setYmsald(id);
            y.setIsSuccess(FAIL);
            y.setTryMessage(e.getMessage().substring(20));
            System.out.println(id + "------异常信息-------------" + e.getMessage());
            y.setUuid(SqenUtils.uuid());
            e.printStackTrace();
            this.saveYmlput(y);
            return uuid;
        }
        long endTime = System.currentTimeMillis();//记录结束时间
        float excTime = (float) (endTime - startTime) / 1000;
        System.out.println("put执行时间：" + excTime + "s------------id=="+uuid);
        return uuid.trim();
    }

    /**
     * map参数拼接
     *
     * @param params
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String createLinkStringByGet(Map<String, String> params) throws UnsupportedEncodingException {
        List<String> keys = new ArrayList<String>(params.keySet());
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = String.valueOf(params.get(key));
            value = URLEncoder.encode(value, "UTF-8");
            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }

    //将javabean实体类转为map类型，然后返回一个map类型的值
    public static Map<String, Object> beanToMap(Object obj, Map params) {
        try {
            PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
            PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj);
            for (int i = 0; i < descriptors.length; i++) {
                String name = descriptors[i].getName();
                if (!"class".equals(name)) {
                    //不为null的
                    if (propertyUtilsBean.getNestedProperty(obj, name) != null && !"".equals(propertyUtilsBean.getNestedProperty(obj, name).toString())) {
                        params.put(name, propertyUtilsBean.getNestedProperty(obj, name));
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return params;
    }

    /**
     * 生成签名
     *
     * @param map
     * @return
     */
    public String getSign(Map map, String secret) {
        StringBuilder s = new StringBuilder();
        //迭代拼接参数
        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        StringBuffer sb = new StringBuffer();
        sb.append(secret);
        while (iterator.hasNext()) {
            Map.Entry<String, Object> enter = (Map.Entry<String, Object>) iterator.next();
            sb.append(enter.getKey()).append(enter.getValue());
        }
        sb.append(secret);
        try {
            return Md5Util.MD5Encode(sb.toString(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Md5Util.MD5Encode(sb.toString(), "utf-8");
    }


    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(10 * 1000);
            conn.setReadTimeout(10 * 1000);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        System.out.println(result);
        return result;
    }


    public String ymlGet(String bknbr) {
        long startTime = System.currentTimeMillis();//记录开始时间
        String resetJson = "";
        String uuid = SqenUtils.uuid();
        try {
            Map baseMap = BaseMap("yml.exp.ep.get", environment.getProperty("app_key_formal"));
            //put业务参数
            baseMap.put("bknbr", bknbr);
            //签名计算
            System.out.println("调用id " + bknbr + "---------start sign" + DateUtils.getDateTime());
            String sign = getSign(baseMap, environment.getProperty("app_secret_formal"));
            baseMap.put("sign", sign);
            resetJson = sendPost(environment.getProperty("api_http_formal"), createLinkStringByGet(baseMap));
            JSONObject j = (JSONObject) JSONObject.parse(resetJson);
            System.out.println("---------end ToYM");
            if (j.containsKey("error_response")) {
                /**
                 * 请求关单号/0为主记录/记录杨明返回json
                 */
                YmlGet y = new YmlGet();
                y.setRequestBknbr(bknbr);
                y.setParent(0);
                y.setIsSuccess(FAIL);
                y.setUuid(uuid);
                y.setYmlApiJson(resetJson);
                y.setTryMessage(j.getJSONObject("error_response").get("desc").toString().replace("\"", ""));
                this.saveYmlget(y);
                return uuid;
            } else {
                //主记录
                JSONArray jsonArray = j.getJSONObject("exp_ep_get_response").getJSONObject("bkdata").getJSONArray("cntrdatas");
                //详细list+
                JSONObject jsonObject = j.getJSONObject("exp_ep_get_response").getJSONObject("bkdata");
                YmlGet y = jsonObject.toJavaObject(YmlGet.class);
                /**
                 * 请求关单号/0为主记录/接口调用是否成功 1成功 0失败/记录杨明返回json/
                 */
                y.setIsSuccess(SUCCESS);
                y.setUuid(uuid);
                //保存子记录
                if (jsonArray.size() > 0) {
                    jsonArray.forEach(ym -> {
                                YmlGet ymlGet = ((JSONObject) ym).toJavaObject(YmlGet.class);
                                try {
                                    MyBeanUtils.copyBeanNotNull2Bean(y, ymlGet);
                                    this.saveYmlget(ymlGet);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

                    );
                }
            }

        } catch (Exception e) {
            /**
             * 请求关单号/0为主记录/记录杨明返回json
             */
            e.printStackTrace();
            YmlGet y = new YmlGet();
            y.setTryMessage(e.getMessage());
            y.setIsSuccess(FAIL);
            y.setUuid(SqenUtils.uuid());
            this.saveYmlget(y);

            return uuid;
        }
        long endTime = System.currentTimeMillis();//记录结束时间

        float excTime = (float) (endTime - startTime) / 1000;

        System.out.println("get执行时间：" + excTime + "s");
        return uuid;

    }

    public String ymlGetJson(String bknbr) {
        long startTime = System.currentTimeMillis();//记录开始时间
        String resetJson = "";
        String uuid = SqenUtils.uuid();
        try {
            Map baseMap = BaseMap("yml.exp.ep.get", environment.getProperty("app_key_formal"));
            //put业务参数
            baseMap.put("bknbr", bknbr);
            //签名计算
            System.out.println("调用id " + bknbr + "---------start sign" + DateUtils.getDateTime());
            String sign = getSign(baseMap, environment.getProperty("app_secret_formal"));
            baseMap.put("sign", sign);
            resetJson = sendPost(environment.getProperty("api_http_formal"), createLinkStringByGet(baseMap));
            return resetJson;
//            if (j.containsKey("error_response")){
//                /**
//                 * 请求关单号/0为主记录/记录杨明返回json
//                 */
//                YmlGet y=new YmlGet();
//                y.setRequestBknbr(bknbr);
//                y.setParent(0);
//                y.setIsSuccess(FAIL);
//                y.setUuid(uuid);
//                y.setYmlApiJson(resetJson);
//                y.setTryMessage(j.getJSONObject("error_response").get("desc").toString().replace("\"",""));
//                this.saveYmlget(y);
//                return uuid;
//            }else {
//                //主记录
//                JSONArray jsonArray=j.getJSONObject("exp_ep_get_response").getJSONObject("bkdata").getJSONArray("cntrdatas");
//                //详细list+
//                JSONObject jsonObject=j.getJSONObject("exp_ep_get_response").getJSONObject("bkdata");
//                YmlGet y =jsonObject.toJavaObject(YmlGet.class);
//                /**
//                 * 请求关单号/0为主记录/接口调用是否成功 1成功 0失败/记录杨明返回json/
//                 */
//                y.setIsSuccess(SUCCESS);
//                y.setUuid(uuid);
//                //保存子记录
//                if(jsonArray.size()>0){
//                    jsonArray.forEach(ym->{
//                                YmlGet ymlGet=((JSONObject)ym).toJavaObject(YmlGet.class);
//                                try {
//                                    MyBeanUtils.copyBeanNotNull2Bean(y,ymlGet);
//                                    this.saveYmlget(ymlGet);
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                }
//                            }
//
//                    );
//                }
//            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            /**
             * 请求关单号/0为主记录/记录杨明返回json
             */
            e.printStackTrace();
//            YmlGet y=new YmlGet();
//            y.setTryMessage(e.getMessage());
//            y.setIsSuccess(FAIL);
//            y.setUuid(uuid);
//            this.saveYmlget(y);

            return resetJson;
        }
        long endTime = System.currentTimeMillis();//记录结束时间

        float excTime = (float) (endTime - startTime) / 1000;

        System.out.println("get执行时间：" + excTime + "s");
        return resetJson;

    }



    @PostMapping(value = {"saveError"})
    public String saveError(String id ,String errMsg){
        YmlPut y = new YmlPut();
        y.setYmsald(id);
        y.setIsSuccess(FAIL);
        y.setTryMessage(errMsg);
        System.out.println(id + "------中转服务器异常信息-------------" +errMsg);
        y.setUuid(SqenUtils.uuid());
        this.saveYmlput(y);
        return id;
    }

    /**
     * 查询阳明接口信息
     *
     * @param ymseqn
     * @return
     */
    public List<Map<String, Object>> getWaait() {
        List<Map<String, Object>> map = null;
        try {
            String sql = "select * from EPENDTA.SACTEIRYM a WHERE a.YMEIRPDAT between '2019-08-16' and '2019-08-17'";
            map = jdbcTemplate.queryForList(sql);
        } catch (EmptyResultDataAccessException e) {
            return map;
        }
        return map;
    }

    /**
     * 查询阳明接口信息
     *
     * @param ymseqn
     * @return
     */
    public List<Map<String, Object>> getTask() {
        List<Map<String, Object>> map = null;
        String today= DateUtil.today();
        //封装时间
       String startData= today+" 00:00:00";
       String endData= today+" 23:59:59";
        try {
            String sql = "select * from EPENDTA.SACTEIRYM a WHERE a.YMEIRPDAT between ? and ? and YMSTAT!='S'";
            map = jdbcTemplate.queryForList(sql,startData,endData);
        } catch (EmptyResultDataAccessException e) {
            return map;
        }
        return map;
    }

    public String ymlPutTask(String id) {
        System.out.println("============ymlPutTask" + DateUtils.getDateTime());
        long startTime = System.currentTimeMillis();//记录开始时间
        String uuid = SqenUtils.uuid();
        YmlPut y = new YmlPut();
        try {
            String resetJson = "";
            //put业务参数
            List<Map<String, Object>> list = this.get(id);
            for (int i = 0; i < list.size(); i++) {
                Thread.sleep(50);
                Map baseMap = BaseMap("yml.exp.ep.pr.put", environment.getProperty("app_key_formal"));
                Map<String, Object> m = mapToBean(list.get(i));
                baseMap.putAll(m);
                //签名计算
                String sign = getSign(baseMap, environment.getProperty("app_secret_formal"));
                baseMap.put("sign", sign);
                System.out.println("============开始调用put" + DateUtils.getDateTime());
                resetJson = sendPost(environment.getProperty("api_http_formal"), createLinkStringByGet(baseMap));
                JSONObject j = (JSONObject) JSONObject.parse(resetJson);
                if (j.containsKey("error_response")) {
                    //记录调用方编号
                    y.setYmsald(id);
                    y.setIsSuccess(FAIL);
                    String msg=  j.getJSONObject("error_response").get("desc").toString().replace("\"", "");
                    if (msg.length()>20){
                        msg.substring(0,19);
                    }
                    y.setTryMessage("msg");
                    y.setUuid(uuid);
                    update(id,"F");
                } else {
                    //记录调用方编号
                    y.setYmsald(id);
                    y.setIsSuccess(SUCCESS);
                    y.setTryMessage("ok");
                    y.setUuid(uuid);
                    update(id,"S");
                }
            }

            this.saveYmlput(y);
        } catch (Exception e) {
            //记录调用方编号
            y.setYmsald(id);
            y.setIsSuccess(FAIL);
            y.setTryMessage(e.getMessage().substring(20));
            System.out.println(id + "------异常信息-------------" + e.getMessage());
            y.setUuid(SqenUtils.uuid());
            e.printStackTrace();
            this.saveYmlput(y);
            update(id,"E");
            return uuid;
        }
        long endTime = System.currentTimeMillis();//记录结束时间
        float excTime = (float) (endTime - startTime) / 1000;
        System.out.println("ymlPutTask执行时间：" + excTime + "s------------id=="+uuid);
        return uuid;
    }

    /**
     * 回调修改状态
     * @param YMSEQN
     * @return
     */
    public void update(String YMSEQN,String status){
        String sql = "update SACTEIRYM set YMSTAT=? where YMSEQN=?";
         jdbcTemplate.update(sql,status,YMSEQN);
    }
}
